﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using DCT.Huiteng.Utility.Log;
using DCT.Huiteng.Utility.DataStruct;

namespace DCT.Huiteng.Utility.Miscellaneous
{
    public class QueueExecution
    {
        public event EventHandler<GenericEventArgs<LogData>> LogEvent;
        public event EventHandler<GenericEventArgs<LogData>> RunThrowErrorEvent;

        public bool LogExecuteTime { get; set; }
        public QueueExecutionContext Context { get; private set; }

        public QueueExecution()
        {            
            this.LogExecuteTime = false;
            this.Context = new QueueExecutionContext();
        }

        public bool Run(IEnumerable<Func<QueueExecutionContext, bool>> executes)
        {
            string str;
            return this.Run(executes, out str);
        }

        public bool Run(IEnumerable<Func<QueueExecutionContext, bool>> executes, out string triggerFalseExecute)
        {
            bool succ = true;
            triggerFalseExecute = "";

            foreach (Func<QueueExecutionContext, bool> execute in executes)
            {
                bool executeResult = false;
                LogData logdata = new LogData()
                {
                    Tag = "QueueExecute"
                };
                string methodName = execute.Method.Name;
                Stopwatch sw = null;
                if (this.LogExecuteTime)
                {
                    sw = Stopwatch.StartNew();
                }

                Dictionary<string, string> loginfo = new Dictionary<string, string>();
                loginfo["name"] = methodName;

                try
                {
                    executeResult = execute(this.Context);

                    logdata.Level = LogLevel.Info;
                }
                catch (Exception ex)
                {
                    executeResult = false;

                    logdata.Level = LogLevel.Error;
                    logdata.Exception = ex;

                    this.OnRunThrowError(this, new GenericEventArgs<LogData>(logdata));
                }                

                if (sw != null)
                {
                    sw.Stop();
                    loginfo["time"] = sw.ElapsedMilliseconds.ToString();
                }

                loginfo["result"] = executeResult.ToString();
                logdata.Msg = LogExtension.FormatDictory(loginfo);

                this.OnLog(this, new GenericEventArgs<LogData>(logdata));

                if (!executeResult)
                {
                    triggerFalseExecute = methodName;
                    succ = false;
                    break;
                }
            }

            return succ;
        }

        protected virtual void OnLog(object sender, GenericEventArgs<LogData> e)
        {
            if (LogEvent != null && e != null)
            {
                this.LogEvent(sender, e);
            }
        }

        protected virtual void OnRunThrowError(object sender, GenericEventArgs<LogData> e)
        {
            if (RunThrowErrorEvent != null && e != null)
            {
                this.RunThrowErrorEvent(sender, e);
            }
        }
    }

    public class QueueExecutionContext : Dictionary<String, object> { 
    }
}
